package com.fcl.utils
{
	import com.fcl.extended.components.GridItemExtended;
	import com.fcl.layout.dto.LDObject;
	
	import flash.utils.getDefinitionByName;
	
	import hr.binaria.asx3m.Asx3mer;
	
	import mx.containers.FormItem;
	import mx.containers.Grid;
	import mx.containers.GridRow;
	import mx.containers.HBox;
	import mx.containers.Panel;
	import mx.containers.TabNavigator;
	import mx.containers.VBox;
	import mx.controls.AdvancedDataGrid;
	import mx.controls.Button;
	import mx.controls.CheckBox;
	import mx.controls.ComboBox;
	import mx.controls.DateField;
	import mx.controls.Label;
	import mx.controls.TextArea;
	import mx.controls.TextInput;
	import mx.controls.advancedDataGridClasses.AdvancedDataGridColumn;
	import mx.core.ClassFactory;
	import mx.states.AddChild;
	
	import org.as3commons.reflect.Accessor;
	import org.as3commons.reflect.Method;
	import org.as3commons.reflect.Type;
	
	import spark.components.RadioButton;
	
	public class DynamicLayoutGenerator
	{
		public function DynamicLayoutGenerator()
		{
		}
		
	
		public static function generateLayoutfromXML(sourceXML:XML):Object{
//			var source:LDObject = Asx3mer.instance.fromXML(sourceXML) as LDObject;
			var source:LDObject =  new FleXMLer().deserialize(sourceXML) as LDObject;
			return convertFromLDObject(source);
		}
		
		private static function convertFromLDObject(source:LDObject):Object{
			var obj:*;
			if(source.fullName != ""){
				var classToInstantiate : Class = getDefinitionByName(source.fullName) as Class;
				var myClassFactory : ClassFactory = new ClassFactory(classToInstantiate);
				obj = myClassFactory.newInstance();
			}
			copyAllProperties(source, obj);
			var objType:Type =  Type.forInstance(obj);
			var objMethod:Method = objType.getMethod("addChild");
			var objAccessor:Accessor = objType.getField("columns") as Accessor;
	
			if(objAccessor != null && objAccessor.name != "" && obj.hasOwnProperty(objAccessor.name)){
				var  j:int = 0;
				var col:Array = new Array();
				try {
					for each(var ldoChild:LDObject in source.childLDOs){
						var objChild:* = convertFromLDObject(ldoChild);
						col[j] = objChild
						j++;
					}
					obj[objAccessor.name] = col;
				} catch(ex:ReferenceError){}
			} else if( objMethod != null){				
				try {
					for each(var ldoChild:LDObject in source.childLDOs){
						var objChild:* = convertFromLDObject(ldoChild);	
						objMethod.invoke(obj, [objChild]);
					}
				} catch(ex:ReferenceError){}
			}
			return obj;
		}
	
		public static function generateXMLFromLayout(source:*):XML{
//			return Asx3mer.instance.toXML(convertToLDObject(source));
			return new FleXMLer().serialize(convertToLDObject(source));
			
		}
		
		private static function convertToLDObject(source:Object):LDObject{
			var ldo:LDObject = new LDObject();
			copyAllProperties(source, ldo);
			var ldoType:Type =  Type.forInstance(source);
			var ldoMethod:Method = ldoType.getMethod("getChildren");
			var ldoAccessor:Accessor = ldoType.getField("columns") as Accessor;
			if(ldoAccessor != null && ldoAccessor.name != "" && source.hasOwnProperty(ldoAccessor.name)){
				var  j:int = 0;
				try {
					for each(var ldoChild:Object in source[ldoAccessor.name]){
						ldo.childLDOs[j] = convertToLDObject(ldoChild);
						j++;
					}
				} catch(ex:ReferenceError){}
			} else if( ldoMethod != null){
				var  j:int = 0;
				try {
					for each(var ldoChild:Object in ldoMethod.invoke(source, null)){
						ldo.childLDOs[j] = convertToLDObject(ldoChild);
						j++;
					}
				} catch(ex:ReferenceError){}
			}
			return ldo;
		}
		
		private static function copyAllProperties(source:Object, target:*){
			var type:Type = Type.forInstance(source);
			var typeTarget:Type = Type.forInstance(target);
			for each(var y:Accessor  in type.accessors)
			{
				if(target.hasOwnProperty(y.name) && (typeTarget.getField(y.name) as Accessor).writeable)
				{
					target[y.name] = source[y.name];
				}				
			}
			if(target.hasOwnProperty("fullName")){
				target["fullName"] = type.fullName;
			}
			
		}
	}
}